package cn.edu.jxau.util;

import java.util.Iterator;

public class LinkedQueue<T> extends Queue<T> {

    private Node<T> head;
    private Node<T> tail;
    private int size;

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {

            private Node<T> cursor = head;

            @Override
            public boolean hasNext() {
                return cursor != null;
            }

            @Override
            public T next() {
                T item = cursor.item;
                cursor = cursor.next;
                return item;
            }
        };
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void enqueue(T item) {

        Node<T> oldTail = tail;
        tail = new Node<>(item);
        if (isEmpty()) {
            head = tail;
        } else {
            oldTail.next = tail;
        }
        size++;
    }

    @Override
    public T dequeue() {

        if (isEmpty()) {
            return null;
        }
        T item = head.item;
        head = head.next;
        if (head == null) {
            tail = null;
        }
        size--;
        return item;
    }

    @Override
    public T look() {

        if (isEmpty()) {
            return null;
        }
        return head.item;
    }

    @Override
    public String toString() {

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("queue size=").append(size).append("\t");
        stringBuilder.append("[");
        if (size == 0) {
            stringBuilder.append("]");
        } else {
            Node<T> cursor = head;
            while (cursor != null) {
                stringBuilder.append(cursor.item).append(",");
                cursor = cursor.next;
            }
            stringBuilder.deleteCharAt(stringBuilder.length() - 1).append("]");
        }
        return stringBuilder.toString();
    }

    private class Node<T> {
        private T item;
        private Node<T> next;

        public Node() {

        }

        public Node(T item) {
            this.item = item;
        }
    }
}
